In [1]:
import json
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import pandas as pd
from animate import animate_trial
Lets find out what the average trial looks like for P0001.
In [2]:
##Find the average pose data at each frame of the data
##List of body parts used in the data
body_parts = [
"R_EYE", "L_EYE", "NOSE", "R_EAR", "L_EAR", "R_SHOULDER", "L_SHOULDER",
"R_ELBOW", "L_ELBOW", "R_WRIST", "L_WRIST", "R_HIP", "L_HIP", "R_KNEE",
"L_KNEE", "R_ANKLE", "L_ANKLE", "R_1STFINGER","R_5THFINGER", "L_1STFINGER", "L_5THFINGER",
"R_1STTOE", "R_5THTOE", "L_1STTOE", "L_5THTOE", "R_CALC", "L_CALC"
]
##Load all data first to avoid reopening files all the time
all_data = []
for trial_number in range(1, 126):
trial_id = str(trial_number).zfill(4)
with open(f'./data/P0001/BB_FT_P0001_T{trial_id}.json') as json_file:
free_throw_data = json.load(json_file)
all_data.append(free_throw_data)
##Initialize dictionaries to store averaged positions for all body parts and the ball at each frame
averaged_positions = {frame: {part: np.zeros(3) for part in body_parts} for frame in range(240)}
averaged_ball_positions = {frame: np.zeros(3) for frame in range(240)}
##Loop over all frames and body parts to sum the positions across trials
for frame in range(240):
for free_throw_data in all_data:
##Sum the positions for all body parts
for part in body_parts:
position = np.array(free_throw_data['tracking'][frame]['data']['player'].get(part, [0, 0, 0]))
averaged_positions[frame][part] += position
##Sum the ball positions
ball_position = np.array(free_throw_data['tracking'][frame]['data'].get('ball', [0, 0, 0]))
averaged_ball_positions[frame] += ball_position
##Average the positions over the 125 trials by divinding by 125
for part in body_parts:
averaged_positions[frame][part] /= 125
averaged_ball_positions[frame] /= 125
##Put the averages into a list of dictionaries, eg the same format as the original data
average_trial_tracking = []
for frame in range(240):
frame_data = {
'frame': frame,
'data': {
'ball': averaged_ball_positions[frame].tolist(), # Add the averaged ball position
'player': {}
}
}
for part in body_parts:
frame_data['data']['player'][part] = averaged_positions[frame][part].tolist()
average_trial_tracking.append(frame_data)
In [3]:
##Find the avergae outcome of a trial characterized by landing coordinate and angle
landing_x = []
landing_y = []
entry_angle = []
for trial_number in range(1,126):
trial_id = str(trial_number).zfill(4)
with open(f'./data/P0001/BB_FT_P0001_T{trial_id}.json') as json_file:
free_throw_data = json.load(json_file)
landing_x.append(free_throw_data['landing_x'])
landing_y.append(free_throw_data['landing_y'])
entry_angle.append(free_throw_data['entry_angle'])
##Find average for each
av_landing_x = sum(landing_x)/len(landing_x)
av_landing_y = sum(landing_y)/len(landing_y)
av_entry_angle = sum(entry_angle)/len(entry_angle)
In [4]:
##Construct an average trial that has the same format as the data so it can be animated
Average_Trial = {
'participant':'P0001',
'trial_id':'average',
'result':np.nan,
'landing_x':av_landing_x,
'landing_y':av_landing_y,
'entry_angle':av_entry_angle,
'tracking':average_trial_tracking
}
In [5]:
##Export the average trial as a json so it can be read by the animation function
with open('Average_Trial.json', 'w') as json_file:
json.dump(Average_Trial, json_file, indent=4) ##I've been told 'indent=4' makes things pretty
Now that we have the data we can animate what an "average trial" looks like
In [6]:
from IPython.display import HTML
anim = animate_trial("Average_Trial.json", azim=290, player_color="green")
HTML(anim.to_jshtml()) ##Converts animation to JavaScript (Works in Jupyter)
Out[6]: